package com.mercadopago;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public final class MercadoPagoPayment {

	private Log logger = LogFactory.getLog(getClass());

	/**
	 * item_id
	 */
	private String itemId;

	/**
	 * name
	 */
	private String nomeItem;

	/**
	 * currency
	 */
	private String currency = MercadoPago.CURRENCY_REAL;

	/**
	 * price
	 */
	private BigDecimal price;

	/**
	 * op_retira
	 */
	private OpcaoRetirada opcaoRetirada;

	/**
	 * shipping_cost
	 */
	private BigDecimal custoFixoEnvio = new BigDecimal(0.0);

	/**
	 * ship_cost_mode
	 */
	private TipoCustoEnvio tipoCustoEnvio;

	/**
	 * seller_op_id
	 */
	private String codigoReferenciaOperacao;

	/**
	 * acc_id
	 */
	private Long numeroContaVendedor;

	/**
	 * token
	 */
	private String token;

	/**
	 * extra_part
	 */
	private String informacaoAdicionaUrl;

	/**
	 * url_succesful
	 */
	private String urlSuccesful;

	/**
	 * url_process
	 */
	private String urlProcess;

	/**
	 * url_cancel
	 */
	private String urlCancel;

	public MercadoPagoPayment() {
		super();
		logger.debug("inicializando MercadoPagoPayment");
	}

	public void setLogger(Log logger) {
		this.logger = logger;
	}

	/**
	 * item_id
	 * @param java.lang.String
	 */
	public void setItemId(String itemId) {
		this.itemId = itemId;
	}

	/**
	 * name
	 * @param java.lang.String
	 */
	public void setNomeItem(String nomeItem) {
		this.nomeItem = nomeItem;
	}

	/**
	 * currency
	 * @param java.lang.String
	 */
	public void setCurrency(String currency) {
		this.currency = currency;
	}

	/**
	 * price
	 * @param java.math.BigDecimal
	 */
	public void setPrice(BigDecimal price) {
		this.price = price;
	}

	/**
	 * op_retira
	 * @param com.mercadopago.OpcaoRetirada
	 */
	public void setOpcaoRetirada(OpcaoRetirada opcaoRetirada) {
		this.opcaoRetirada = opcaoRetirada;
	}

	/**
	 * shipping_cost
	 * @param java.math.BigDecimal
	 */
	public void setCustoFixoEnvio(BigDecimal custoFixoEnvio) {
		this.custoFixoEnvio = custoFixoEnvio;
	}

	/**
	 * ship_cost_mode
	 * @param com.mercadopago.TipoCustoEnvio
	 */
	public void setTipoCustoEnvio(TipoCustoEnvio tipoCustoEnvio) {
		this.tipoCustoEnvio = tipoCustoEnvio;
	}

	/**
	 * seller_op_id
	 * @param java.lang.String
	 */
	public void setCodigoReferenciaOperacao(String codigoReferenciaOperacao) {
		this.codigoReferenciaOperacao = codigoReferenciaOperacao;
	}

	/**
	 * acc_id
	 * @param java.lang.Long
	 */
	public void setNumeroContaVendedor(Long numeroContaVendedor) {
		this.numeroContaVendedor = numeroContaVendedor;
	}

	/**
	 * token
	 * @param java.lang.String
	 */
	public void setToken(String token) {
		this.token = token;
	}

	/**
	 * extra_part
	 * @param java.lang.String
	 */
	public void setInformacaoAdicionaUrl(String informacaoAdicionaUrl) {
		this.informacaoAdicionaUrl = informacaoAdicionaUrl;
	}

	/**
	 * url_succesfull
	 * @param java.lang.String
	 */
	public void setUrlSuccesful(String urlSuccesful) {
		this.urlSuccesful = urlSuccesful;
	}

	/**
	 * url_process
	 * @param java.lang.String
	 */
	public void setUrlProcess(String urlProcess) {
		this.urlProcess = urlProcess;
	}

	/**
	 * url_cancel
	 * @param java.lang.String
	 */
	public void setUrlCancel(String urlCancel) {
		this.urlCancel = urlCancel;
	}

	/**
	 * valida parametros
	 * @throws MercadoPagoPaymentException
	 */
	private void validade() throws MercadoPagoPaymentException {
		logger.debug("inicializando validação de parametros");

		logger.debug("validando itemId.");
		if (itemId == null || itemId.equals(""))
			throw new MercadoPagoPaymentException("itemId inválido.");

		logger.debug("validando nomeItem.");
		if (nomeItem == null || nomeItem.equals(""))
			throw new MercadoPagoPaymentException("nomeItem inválido.");

		logger.debug("validando price.");
		if (price == null || price.equals(new BigDecimal(0.0)))
			throw new MercadoPagoPaymentException("price inválido.");

		logger.debug("validando opcaoRetirada.");
		if (opcaoRetirada == null)
			throw new MercadoPagoPaymentException("opcaoRetirada inválida.");

		logger.debug("validando tipoCustoEnvio.");
		if (tipoCustoEnvio == null)
			throw new MercadoPagoPaymentException("tipoCustoEnvio inválido.");

		logger.debug("validando codigoReferenciaOperacao.");
		if (codigoReferenciaOperacao == null
				|| codigoReferenciaOperacao.equals(""))
			throw new MercadoPagoPaymentException(
					"codigoReferenciaOperacao inválido.");

		logger.debug("validando numeroContaVendedor.");
		if (numeroContaVendedor == null || numeroContaVendedor == 0L)
			throw new MercadoPagoPaymentException(
					"numeroContaVendedor inválido.");

		logger.debug("validando token.");
		if (token == null || token.equals(""))
			throw new MercadoPagoPaymentException("token inválido.");

		logger.debug("validando urlSuccesful.");
		if (urlSuccesful == null || urlSuccesful.equals(""))
			throw new MercadoPagoPaymentException("urlSuccesful inválido.");

		logger.debug("validando urlProcess.");
		if (urlProcess == null || urlProcess.equals(""))
			throw new MercadoPagoPaymentException("urlProcess inválido.");

		logger.debug("validando urlCancel.");
		if (urlCancel == null || urlCancel.equals(""))
			throw new MercadoPagoPaymentException("urlCancel inválido.");
	}

	/**
	 * 
	 * @return URL de pagamento do mercado pago
	 * @throws MercadoPagoPaymentException
	 */
	public String sendDataPayment() throws MercadoPagoPaymentException {
		validade();

		logger.debug("enviando dados para pagamento");

		PostMethod postMethod = new PostMethod(MercadoPago.URL_SUBMIT_PAYMENT);
		
		logger.debug("configurando parametros de pagamento");
		postMethod.addParameter("item_id", itemId);
		postMethod.addParameter("name", nomeItem);
		postMethod.addParameter("currency", currency);
		postMethod.addParameter("price", String.valueOf(price.doubleValue()));
		postMethod.addParameter("op_retira", opcaoRetirada.value());
		postMethod.addParameter("shipping_cost", String.valueOf(custoFixoEnvio.doubleValue()));
		postMethod.addParameter("ship_cost_mode", tipoCustoEnvio.value());
		postMethod.addParameter("seller_op_id", codigoReferenciaOperacao);
		postMethod.addParameter("acc_id", numeroContaVendedor.toString());
		postMethod.addParameter("token", token);
		if (informacaoAdicionaUrl != null)
			postMethod.addParameter("extra_part", informacaoAdicionaUrl);
		postMethod.addParameter("url_succesfull", urlSuccesful);
		postMethod.addParameter("url_process", urlProcess);
		postMethod.addParameter("url_cancel", urlCancel);

		try {
			logger.debug("Configure httpclient");
			HttpClient httpClient = new HttpClient();

			logger.debug("execute send post data payment");
			int statusResponse = httpClient.executeMethod(postMethod);
			
			logger.debug("verificando status da resposta com comunicação com mercado pago");
			if(statusResponse != HttpStatus.SC_OK) {
				throw new MercadoPagoPaymentException("Erro ao efetuar comunicação com mercado pago.");
			} else {
				logger.debug("Processando a resposta do mercado pago.");
				InputStreamReader inputStreamReader = new InputStreamReader(postMethod.getResponseBodyAsStream(), postMethod.getResponseCharSet());
				BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
				
				StringBuffer stringBuffer = new StringBuffer();
				String line = bufferedReader.readLine();
				while(line != null) {
					stringBuffer.append(line);
					line = bufferedReader.readLine();
				}
				
				return stringBuffer.toString();
			}
		} catch (HttpException e) {
			throw new MercadoPagoPaymentException(e);
		} catch (IOException e) {
			throw new MercadoPagoPaymentException(e);
		} finally {
			logger.debug("liberar conexão de envio de dados para mercado pago");
			postMethod.releaseConnection();
		}
	}

}